package com.ruoyi.system.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Lists;
import com.ruoyi.common.annotation.DataSource;
import com.ruoyi.common.enums.DataSourceType;
import com.ruoyi.system.domain.WQcCementMixPlant;
import com.ruoyi.system.domain.WQcCementMixPlantData;
import com.ruoyi.system.domain.XxSectionPlan;
import com.ruoyi.system.mapper.WQcCementMixPlantDataMapper;
import com.ruoyi.system.mapper.WQcCementMixPlantFormulaMapper;
import com.ruoyi.system.mapper.WQcCementMixPlantMapper;
import com.ruoyi.system.mapper.XxSectionPlanMapper;
import com.ruoyi.system.service.OutCementService;
import com.ruoyi.system.vo.*;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

import static com.ruoyi.system.utils.XxUtils.getSectionCementList;

/**
 * 水泥产量标段服务
 *
 * @Author LiBingyan
 * @Date 2022/3/20 17:13
 * @Version 1.0
 **/
@Service
public class OutCementServiceImpl implements OutCementService {

    @Autowired
    WQcCementMixPlantDataMapper wQcCementMixPlantDataMapper;
    @Autowired
    WQcCementMixPlantFormulaMapper wQcCementMixPlantFormulaMapper;
    @Autowired
    WQcCementMixPlantMapper wQcCementMixPlantMapper;
    @Autowired
    XxSectionPlanMapper xxSectionPlanMapper;

    /**
     * 通过标段名称获取实际产量,和预定产量比较
     *
     * @param cementRequest
     * @return
     */

    @Override
    @DataSource(value = DataSourceType.SLAVE2)
    public CementResponse getSectionCreateRatio(CementRequest cementRequest) {
        CementResponse cementResponse = new CementResponse();
        List<String> formulaName1 = getFormulaName(cementRequest);
        cementRequest.setFormulaNames(formulaName1);
        OutCementService outCementService = (OutCementService) AopContext.currentProxy();
        cementResponse = outCementService.buildCementResponse(cementResponse, cementRequest);
        cementResponse = outCementService.buildCementResponse2(cementResponse, cementRequest);
        TotalProgress totalProgress = new TotalProgress();
        BigDecimal total = new BigDecimal(0);
        BigDecimal completed = new BigDecimal(0);
        for (FormulaName formulaName : cementResponse.getFormula()) {
            BigDecimal completed1 = formulaName.getCompleted();
            BigDecimal total1 = formulaName.getTotal();
            total = total.add(total1 != null ? total1 : new BigDecimal(0));
            completed = completed.add(completed1 != null ? completed1 : new BigDecimal(0));
        }
        totalProgress.setTotal(total.divide(new BigDecimal(1),2, RoundingMode.HALF_UP));
        totalProgress.setCompleted(completed.divide(new BigDecimal(1),2, RoundingMode.HALF_UP));
        cementResponse.setTotalProgress(totalProgress);
        return cementResponse;
    }

    /**
     * 多数据源导致
     *
     * @param cementResponse
     */
    @Override
    @DataSource(value = DataSourceType.MASTER)
    public CementResponse buildCementResponse(CementResponse cementResponse, CementRequest cementRequest) {
        LambdaQueryWrapper<XxSectionPlan> xxSectionPlanLambdaQueryWrapper = new LambdaQueryWrapper<>();
        xxSectionPlanLambdaQueryWrapper.eq(XxSectionPlan::getSectionName, cementRequest.getSectionName());
        XxSectionPlan xxSectionPlan = xxSectionPlanMapper.selectOne(xxSectionPlanLambdaQueryWrapper);
        FormulaName c15 = new FormulaName();
        c15.setName("C15");
        c15.setTotal(xxSectionPlan.getC15Plan() != null ? xxSectionPlan.getC15Plan().divide(new BigDecimal(1),4, RoundingMode.HALF_UP) : new BigDecimal(0));
        FormulaName c20 = new FormulaName();
        c20.setName("C20");
        c20.setTotal(xxSectionPlan.getC20Plan() != null ? xxSectionPlan.getC20Plan().divide(new BigDecimal(1),4, RoundingMode.HALF_UP) : new BigDecimal(0));
        FormulaName c25 = new FormulaName();
        c25.setName("C25");
        c25.setTotal(xxSectionPlan.getC25Plan() != null ? xxSectionPlan.getC25Plan().divide(new BigDecimal(1),4, RoundingMode.HALF_UP) : new BigDecimal(0));
        FormulaName c30 = new FormulaName();
        c30.setName("C30");
        c30.setTotal(xxSectionPlan.getC30Plan() != null ? xxSectionPlan.getC30Plan().divide(new BigDecimal(1),4, RoundingMode.HALF_UP) : new BigDecimal(0));
        FormulaName c35 = new FormulaName();
        c35.setName("C35");
        c35.setTotal(xxSectionPlan.getC35Plan() != null ? xxSectionPlan.getC35Plan().divide(new BigDecimal(1),4, RoundingMode.HALF_UP) : new BigDecimal(0));
        FormulaName c40 = new FormulaName();
        c40.setName("C40");
        c40.setTotal(xxSectionPlan.getC40Plan() != null ? xxSectionPlan.getC40Plan().divide(new BigDecimal(1),4, RoundingMode.HALF_UP) : new BigDecimal(0));
        FormulaName c45 = new FormulaName();
        c45.setName("C45");
        c45.setTotal(xxSectionPlan.getC45Plan() != null ? xxSectionPlan.getC45Plan().divide(new BigDecimal(1),4, RoundingMode.HALF_UP) : new BigDecimal(0));
        FormulaName c50 = new FormulaName();
        c50.setName("C50");
        c50.setTotal(xxSectionPlan.getC50Plan() != null ? xxSectionPlan.getC50Plan().divide(new BigDecimal(1),4, RoundingMode.HALF_UP) : new BigDecimal(0));
        FormulaName c55 = new FormulaName();
        c55.setName("C55");
        c55.setTotal(xxSectionPlan.getC55Plan() != null ? xxSectionPlan.getC55Plan().divide(new BigDecimal(1),4, RoundingMode.HALF_UP) : new BigDecimal(0));
        FormulaName c60 = new FormulaName();
        c60.setName("C60");
        c60.setTotal(xxSectionPlan.getC60Plan() != null ? xxSectionPlan.getC60Plan().divide(new BigDecimal(1),4, RoundingMode.HALF_UP) : new BigDecimal(0));
        FormulaName c65 = new FormulaName();
        c65.setName("C65");
        c65.setTotal(xxSectionPlan.getC65Plan() != null ? xxSectionPlan.getC65Plan().divide(new BigDecimal(1),4, RoundingMode.HALF_UP) : new BigDecimal(0));
        FormulaName c70 = new FormulaName();
        c70.setName("C70");
        c70.setTotal(xxSectionPlan.getC70Plan() != null ? xxSectionPlan.getC70Plan().divide(new BigDecimal(1),4, RoundingMode.HALF_UP) : new BigDecimal(0));
        FormulaName m75 = new FormulaName();
        m75.setName("M7.5");
        m75.setTotal(xxSectionPlan.getM7dian5Plan() != null ? xxSectionPlan.getM7dian5Plan().divide(new BigDecimal(1),4, RoundingMode.HALF_UP) : new BigDecimal(0));
        List<FormulaName> formulaNameList = Lists.newArrayList(c15, c20, c25, c30, c35, c40, c45, c50, c55, c60, c65, c70, m75);
        cementResponse.setFormula(formulaNameList);
        return cementResponse;
    }

    @DataSource(value = DataSourceType.SLAVE2)
    @Override
    public CementResponse buildCementResponse2(CementResponse cementResponse, CementRequest cementRequest) {
        List<String> sectionCementList = getSectionCementList(cementRequest.getSectionName());
        LambdaQueryWrapper<WQcCementMixPlant> wQcCementMixPlantLambdaQueryWrapper = new LambdaQueryWrapper<>();
        wQcCementMixPlantLambdaQueryWrapper.in(WQcCementMixPlant::getDevicesn, sectionCementList).in(WQcCementMixPlant::getFormulaname, cementRequest.getFormulaNames()).ge(WQcCementMixPlant::getDischargetime, "2022-02-02 00:00:00");
        List<WQcCementMixPlant> wQcCementMixPlants = wQcCementMixPlantMapper.selectList(wQcCementMixPlantLambdaQueryWrapper);
        Map<String, List<WQcCementMixPlant>> wQcCementMixPlantsMap = wQcCementMixPlants.stream().collect(Collectors.groupingBy(wQcCementMixPlant -> wQcCementMixPlant.getFormulaname()));
        Map<String, List<Integer>> pkIdMap = new LinkedHashMap<>();
        for (Map.Entry<String, List<WQcCementMixPlant>> stringListEntry : wQcCementMixPlantsMap.entrySet()) {
            List<Integer> pkIdList = new ArrayList<>();
            pkIdMap.put(stringListEntry.getKey(), pkIdList);
            for (WQcCementMixPlant wQcCementMixPlant : stringListEntry.getValue()) {
                pkIdList.add(wQcCementMixPlant.getId());
            }
        }
        // 已完成的map
        for (Map.Entry<String, List<Integer>> stringListEntry : pkIdMap.entrySet()) {
            LambdaQueryWrapper<WQcCementMixPlantData> wQcCementMixPlantDataLambdaQueryWrapper = new LambdaQueryWrapper<>();
            wQcCementMixPlantDataLambdaQueryWrapper.in(WQcCementMixPlantData::getPkId, stringListEntry.getValue());
            List<WQcCementMixPlantData> wQcCementMixPlantData = wQcCementMixPlantDataMapper.selectList(wQcCementMixPlantDataLambdaQueryWrapper);
            BigDecimal listSummation = getListSummation(wQcCementMixPlantData);
            putActInfoByFormulaName(stringListEntry.getKey(), listSummation, cementResponse);
        }
        return cementResponse;
    }

    /**
     * 拌合站逐日产量统计
     *
     * @param cementRequest
     * @return
     */
    @Override
    @DataSource(value = DataSourceType.SLAVE2)
    public List<CementOneDay> getSectionOneDay(CementRequest cementRequest) {
        List<String> sectionCementList = getSectionCementList(cementRequest.getSectionName());
        LambdaQueryWrapper<WQcCementMixPlant> wQcCementMixPlantLambdaQueryWrapper = new LambdaQueryWrapper<>();
        String formatDateTime;
        wQcCementMixPlantLambdaQueryWrapper.in(WQcCementMixPlant::getDevicesn, sectionCementList).last("order by dischargeTime desc  limit 1");
        WQcCementMixPlant wQcCementMixPlantOne = wQcCementMixPlantMapper.selectOne(wQcCementMixPlantLambdaQueryWrapper);
        if (Objects.equals(cementRequest.getTime(), null)) {
            Date now = wQcCementMixPlantOne.getDischargetime();
            DateTime newDate2 = DateUtil.offsetDay(now, -7);
            DateTime newDate2Start = DateUtil.beginOfDay(newDate2);
            formatDateTime = DateUtil.formatDateTime(newDate2Start);
        } else {
            DateTime newDate2 = DateUtil.offsetDay(cementRequest.getTime(), -7);
            DateTime newDate2Start = DateUtil.beginOfDay(newDate2);
            formatDateTime = DateUtil.formatDateTime(newDate2Start);
        }
        wQcCementMixPlantLambdaQueryWrapper.in(WQcCementMixPlant::getDevicesn, sectionCementList).ge(WQcCementMixPlant::getDischargetime, formatDateTime).last("order by dischargeTime desc");
        List<WQcCementMixPlant> wQcCementMixPlants = wQcCementMixPlantMapper.selectList(wQcCementMixPlantLambdaQueryWrapper);
        for (WQcCementMixPlant wQcCementMixPlant : wQcCementMixPlants) {
            Date dischargetime = wQcCementMixPlant.getDischargetime();
            String format = DateUtil.format(dischargetime, "yyyy-MM-dd");
            wQcCementMixPlant.setDischargetime(DateUtil.parse(format));
        }
        // 时间
        Map<Date, List<WQcCementMixPlant>> wQcCementMixPlantsMap = wQcCementMixPlants.stream().collect(Collectors.groupingBy(wQcCementMixPlant -> wQcCementMixPlant.getDischargetime()));
        // 时间
        Map<Date, List<Integer>> pkIdMap = new LinkedHashMap<>();
        for (Map.Entry<Date, List<WQcCementMixPlant>> stringListEntry : wQcCementMixPlantsMap.entrySet()) {
            List<Integer> pkIdList = new ArrayList<>();
            pkIdMap.put(stringListEntry.getKey(), pkIdList);
            for (WQcCementMixPlant wQcCementMixPlant : stringListEntry.getValue()) {
                pkIdList.add(wQcCementMixPlant.getId());
            }
        }
        List<CementOneDay> returnList = new ArrayList<>();
        for (Map.Entry<Date, List<Integer>> stringListEntry : pkIdMap.entrySet()) {
            LambdaQueryWrapper<WQcCementMixPlantData> wQcCementMixPlantDataLambdaQueryWrapper = new LambdaQueryWrapper<>();
            wQcCementMixPlantDataLambdaQueryWrapper.in(WQcCementMixPlantData::getPkId, stringListEntry.getValue());
            List<WQcCementMixPlantData> wQcCementMixPlantData = wQcCementMixPlantDataMapper.selectList(wQcCementMixPlantDataLambdaQueryWrapper);
            BigDecimal listSummation = getListSummation(wQcCementMixPlantData);
            // 千克转为吨
            listSummation=listSummation != null ? listSummation.divide(new BigDecimal(1000),2, RoundingMode.HALF_UP) : new BigDecimal(0);
            CementOneDay cementOneDay = new CementOneDay();
            cementOneDay.setProduct(listSummation);
            cementOneDay.setTime(DateUtil.formatDate(stringListEntry.getKey()));
            if (Objects.equals(listSummation, null) || Objects.equals(listSummation.toString(), "0")) {
                continue;
            }
            returnList.add(cementOneDay);
        }
        returnList.sort(Comparator.comparing(CementOneDay::getTime));
        Collections.reverse(returnList);
        return returnList;
    }

    /**
     * 获取标段上的配方名称
     *
     * @param cementRequest
     * @return
     */
    @DataSource(value = DataSourceType.SLAVE2)
    @Override
    public List<String> getFormulaName(CementRequest cementRequest) {
        List<String> sectionCementList = getSectionCementList(cementRequest.getSectionName());
        QueryWrapper<WQcCementMixPlant> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("distinct formulaName").in("deviceSn", sectionCementList);
        List<WQcCementMixPlant> wQcCementMixPlants = wQcCementMixPlantMapper.selectList(queryWrapper);
        List<String> stringList = new ArrayList<>();
        for (WQcCementMixPlant wQcCementMixPlant : wQcCementMixPlants) {
            stringList.add(wQcCementMixPlant.getFormulaname());
        }
        return stringList;
    }

    /**
     * 对LIST求和
     *
     * @param wQcCementMixPlantDataList
     * @return
     */
    private BigDecimal getListSummation(List<WQcCementMixPlantData> wQcCementMixPlantDataList) {
        BigDecimal sum = new BigDecimal(0);
        for (WQcCementMixPlantData wQcCementMixPlantData1 : wQcCementMixPlantDataList) {
            BigDecimal add = sum.add(new BigDecimal(wQcCementMixPlantData1.getAgg1())).add(new BigDecimal(wQcCementMixPlantData1.getAgg2())).
                    add(new BigDecimal(wQcCementMixPlantData1.getAgg3())).add(new BigDecimal(wQcCementMixPlantData1.getAgg4())).
                    add(new BigDecimal(wQcCementMixPlantData1.getAgg5())).add(new BigDecimal(wQcCementMixPlantData1.getAgg6())).add(new BigDecimal(wQcCementMixPlantData1.getCement1())).
                    add(new BigDecimal(wQcCementMixPlantData1.getCement2())).add(new BigDecimal(wQcCementMixPlantData1.getCement3())).
                    add(new BigDecimal(wQcCementMixPlantData1.getCement4())).add(new BigDecimal(wQcCementMixPlantData1.getWater())).add(new BigDecimal(wQcCementMixPlantData1.getAdditive1()))
                    .add(new BigDecimal(wQcCementMixPlantData1.getAdditive2())).add(new BigDecimal(wQcCementMixPlantData1.getAdditive3())).
                    add(new BigDecimal(wQcCementMixPlantData1.getFlyash1())).add(new BigDecimal(wQcCementMixPlantData1.getFlyash2()));
            sum = add;
        }
        return sum;
    }

    /**
     * 根据formula 放入已完成对应位置
     *
     * @param formula
     * @param bigDecimal
     * @param cementResponse
     */
    private void putActInfoByFormulaName(String formula, BigDecimal bigDecimal, CementResponse cementResponse) {
        switch (formula) {
            case "C15":
                cementResponse.getFormula().get(0).setCompleted(bigDecimal.divide(new BigDecimal(1000),4, RoundingMode.HALF_UP));
                break;
            case "C20":
                cementResponse.getFormula().get(1).setCompleted(bigDecimal.divide(new BigDecimal(1000),4, RoundingMode.HALF_UP));
                break;
            case "C25":
                cementResponse.getFormula().get(2).setCompleted(bigDecimal.divide(new BigDecimal(1000),4, RoundingMode.HALF_UP));
                break;
            case "C30":
                cementResponse.getFormula().get(3).setCompleted(bigDecimal.divide(new BigDecimal(1000),4, RoundingMode.HALF_UP));
                break;
            case "C35":
                cementResponse.getFormula().get(4).setCompleted(bigDecimal.divide(new BigDecimal(1000),4, RoundingMode.HALF_UP));
                break;
            case "C40":
                cementResponse.getFormula().get(5).setCompleted(bigDecimal.divide(new BigDecimal(1000),4, RoundingMode.HALF_UP));
                break;
            case "C45":
                cementResponse.getFormula().get(6).setCompleted(bigDecimal.divide(new BigDecimal(1000),4, RoundingMode.HALF_UP));
                break;
            case "C50":
                cementResponse.getFormula().get(7).setCompleted(bigDecimal.divide(new BigDecimal(1000),4, RoundingMode.HALF_UP));
                break;
            case "C55":
                cementResponse.getFormula().get(8).setCompleted(bigDecimal.divide(new BigDecimal(1000),4, RoundingMode.HALF_UP));
                break;
            case "C60":
                cementResponse.getFormula().get(9).setCompleted(bigDecimal.divide(new BigDecimal(1000),4, RoundingMode.HALF_UP));
                break;
            case "C65":
                cementResponse.getFormula().get(10).setCompleted(bigDecimal.divide(new BigDecimal(1000),4, RoundingMode.HALF_UP));
                break;
            case "C70":
                cementResponse.getFormula().get(11).setCompleted(bigDecimal.divide(new BigDecimal(1000),4, RoundingMode.HALF_UP));
                break;
            case "M7.5":
                cementResponse.getFormula().get(12).setCompleted(bigDecimal.divide(new BigDecimal(1000),4, RoundingMode.HALF_UP));
                break;
            default:
        }
    }


}
